<script>
import { ref, onMounted, watch } from 'vue';

export default {
  name: 'ColorPicker',
  components: {},
  props: { color: { type: Array, default: () => [0, 0, 0] } },

  setup(props, { emit }) {
    let can = ref(null);
    let cur = ref(null);
    let bgColor = ref(null);
    const width = 256;
    const curColor = props.color
      ? `rgba(${props.color.join(',')},1)`
      : 'rgba(255,0,0,1)';
    let rgbValue = ref([]);
    let colorR = ref(props.color[0]);
    let colorG = ref(props.color[1]);
    let colorB = ref(props.color[2]);

    onMounted(() => {
      can = document.getElementById('canvas');
      cur = document.getElementById('cur');
      // bgColor = document.getElementById('bgColor')
      // bgColor.style.backgroundColor = curColor
      colorBar();
      colorBox(curColor);
      can.addEventListener('click', (e) => {
        const coorX = e.offsetX || e.layerX;
        const coorY = e.offsetY || e.layerY;
        const ctx = can.getContext('2d');
        const imgData = ctx.getImageData(coorX, coorY, 1, 1);
        const { data } = imgData;
        const rgbaStr = [data[0], data[1], data[2]];
        rgbValue = rgbaStr;
        emit('exportColor', rgbaStr);
        if (coorX && coorX >= 80 && coorY >= 275 && coorY < 300) {
          colorBox(`rgba(${rgbaStr.join(',')})`);
        }
        // bgColor.style.backgroundColor = `rgba(${rgbaStr.join(',')})`
        ctx.beginPath();
        ctx.arc(50, 285, 15, 0, 2 * Math.PI);
        ctx.fillStyle = `rgba(${rgbaStr.join(',')})`;
        ctx.fill();
        colorR.value = rgbaStr[0];
        colorG.value = rgbaStr[1];
        colorB.value = rgbaStr[2];
        cur.style.left = `${coorX}px`;
        cur.style.top = `${coorY}px`;
        // 128 === 256/2  亮色边框用黑色， 暗色用白色
        cur.style.outlineColor =
          rgbaStr[0] > 128 || rgbaStr[1] > 128 || rgbaStr[2] > 128
            ? '#000'
            : '#fff';
      });
    });

    // 绘制图例
    const colorBar = () => {
      const ctx = can.getContext('2d');
      const gradientBar = ctx.createLinearGradient(0, 280, width, 280);
      gradientBar.addColorStop(0, '#f00');
      gradientBar.addColorStop(1 / 6, '#f0f');
      gradientBar.addColorStop(2 / 6, '#00f');
      gradientBar.addColorStop(3 / 6, '#0ff');
      gradientBar.addColorStop(4 / 6, '#0f0');
      gradientBar.addColorStop(5 / 6, '#ff0');
      gradientBar.addColorStop(1, '#f00');
      ctx.fillStyle = gradientBar;
      ctx.fillRect(80, 275, width - 50, 20);
    };

    const colorBox = (color) => {
      const ctx = can.getContext('2d');
      // 底色填充，也就是（举例红色）到白色
      const gradientBase = ctx.createLinearGradient(30, 0, width + 30, 0);
      gradientBase.addColorStop(1, color);
      gradientBase.addColorStop(0, 'rgba(255,255,255,1)');
      ctx.fillStyle = gradientBase;
      ctx.fillRect(30, 0, width, width);
      // 第二次填充，黑色到透明
      const gradientScreen = ctx.createLinearGradient(0, 0, 0, width);
      gradientScreen.addColorStop(0, 'rgba(0,0,0,0)');
      gradientScreen.addColorStop(1, 'rgba(0,0,0,1)');
      ctx.fillStyle = gradientScreen;
      ctx.fillRect(30, 0, width, width);
      // 绘制圆环
      ctx.beginPath();
      ctx.arc(50, 285, 15, 0, 2 * Math.PI);
      ctx.fillStyle = color;
      ctx.fill();
    };

    // 输入框改变事件
    const colorChange = () => {
      if (colorR.value < 0 || colorR.value > 255) return;
      if (colorG.value < 0 || colorG.value > 255) return;
      if (colorB.value < 0 || colorB.value > 255) return;

      const rgba =
        'rgba(' +
        colorR.value +
        ',' +
        colorG.value +
        ',' +
        colorB.value +
        ',' +
        '1)';
      colorBox(rgba);
      // bgColor.style.backgroundColor = rgba

      // 显示对应选中点
      const ctx = can.getContext('2d');
      const imgData = ctx.getImageData(30, 0, width, width);
      for (let y = 0; y < width; y++) {
        for (let x = 0; x < width; x++) {
          const r = imgData.data[0 + (width * y + x) * 4];
          const g = imgData.data[1 + (width * y + x) * 4];
          const b = imgData.data[2 + (width * y + x) * 4];
          const a = imgData.data[3 + (width * y + x) * 4];

          if (
            r === Number(colorR.value) &&
            g === Number(colorG.value) &&
            b === Number(colorB.value) &&
            a === 255
          ) {
            cur.style.left = `${x}px`;
            cur.style.top = `${y}px`;
            // 128 === 256/2  亮色边框用黑色， 暗色用白色
            cur.style.outlineColor =
              colorR.value > 128 || colorG.value > 128 || colorB.value > 128
                ? '#000'
                : '#fff';
          }
        }
      }
      const rgbaStr = [colorR.value, colorG.value, colorB.value];
      emit('exportColor', rgbaStr);
    };

    watch(
      () => props.color,
      () => {
        if (props.color?.length) {
          const color = props.color;
          //重置tab
          colorR.value = color[0];
          colorG.value = color[1];
          colorB.value = color[2];
        } else {
          colorR.value = 0;
          colorG.value = 0;
          colorB.value = 0;
        }
        colorChange();
      }
    );

    return {
      colorBar,
      colorBox,
      colorChange,
      rgbValue,
      colorR,
      colorG,
      colorB,
    };
  },
};
</script>

<template>
  <div className="colorPicker">
    <div className="wrapper">
      <canvas id="canvas"
              className="canvas"
              width="300"
              height="300"
              ref="can"></canvas>
      <em id="cur"
          className="cur"
          ref="cur"></em>
    </div>
    <!-- <div class="show">
            <span id="bgColor" class="bgColor" ref="bgColor"></span>
        </div> -->
    <ul class="number">
      <li>
        <a-input-number v-model:value="colorR"
                        @change="colorChange"
                        min="0"
                        max="255" />
        <label for="">R</label>
      </li>
      <li>
        <a-input-number v-model:value="colorG"
                        @change="colorChange"
                        min="0"
                        max="255" />
        <label for="">G</label>
      </li>
      <li>
        <a-input-number v-model:value="colorB"
                        @change="colorChange"
                        min="0"
                        max="255" />
        <label for="">B</label>
      </li>
    </ul>
  </div>
</template>

<style lang="scss">
.colorPicker {
  width: 300px;
  height: auto;
  // background: #fff;

  .wrapper {
    width: 300px;
    height: 300px;
    position: relative;
    margin-bottom: 0.1rem;

    .canvas {
      cursor: crosshair;
    }

    .cur {
      width: 4px;
      height: 4px;
      margin-left: -1px;
      margin-top: -1px;
      outline: 2px solid rgba(0, 0, 0, 0);
      position: absolute;
      border-radius: 50%;
    }
  }

  .show {
    width: 100%;
    height: 0.5rem;

    .bgColor {
      width: 0.4rem;
      height: 0.4rem;
      display: inline-block;
      border-radius: 50%;
    }
  }
  .number {
    width: 256px;
    display: flex;
    justify-content: space-between;
    margin-left: 30px;

    li {
      display: flex;
      flex-direction: column;
      justify-content: center;
      text-align: center;
      .ant-input-number {
        margin-bottom: 0.1rem;
        text-align: center;
        width: 75px;
        .ant-input-number-input {
          text-align: center;
        }
      }
      label {
        font-size: 0.2rem;
        font-weight: 600;
        color: #fff;
      }
    }
  }
}
</style>
